#include "MiniComClient.h"

#include <QTimer>
#include <QThread>

#include <iostream> 
#include <boost/bind.hpp> 
#include <boost/asio/serial_port.hpp> 
#include <boost/thread.hpp> 
#include <boost/lexical_cast.hpp> 
#include <boost/date_time/posix_time/posix_time_types.hpp> 
#include "QtAsioThread.h"


using namespace std; 
using namespace boost::asio;
namespace vkbrd
{
	miniComClient::miniComClient( boost::asio::io_service& io_service, unsigned int baud, const string& _device) : 
ioService(io_service), 
serialPort(io_service, _device)
{
	if (!serialPort.is_open()) 
	{ 
		cerr << "Failed to open serial port\n"; 
		return; 
	} 

	serialPort.set_option(serial_port_base::baud_rate(baud)); // set the baud rate after the port has been opened 
	serialPort.set_option(serial_port_base::parity(serial_port_base::parity::none));
	serialPort.set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::one));
	serialPort.set_option(serial_port_base::character_size(8));

	read_start();
}

void miniComClient::read_start( void )
{
	// Start an asynchronous read and call read_complete when it completes or fails 
	serialPort.async_read_some(boost::asio::buffer(read_msg_, maxReadLength), 
		boost::bind(&miniComClient::read_complete, 
		this, 
		boost::asio::placeholders::error, 
		boost::asio::placeholders::bytes_transferred));
}

void miniComClient::read_complete( const boost::system::error_code& error, int bytes_transferred )
{
	// the asynchronous read operation has now completed or failed and returned an error 
	if (!error) 
	{ // read completed, so process the data 
		emit receivedData((unsigned char *)read_msg_, bytes_transferred);

		read_start(); // start waiting for another asynchronous read again 
	} 
	else 
		do_close(error);
}

void miniComClient::do_write( unsigned char msg )
{
	// callback to handle write call from outside this class 
	bool write_in_progress = !writeMsgs.empty(); // is there anything currently being written? 
	writeMsgs.push_back(msg); // store in write buffer 
	if (!write_in_progress) // if nothing is currently being written, then start 
		write_start();
}

void miniComClient::write_start( void )
{
	// Start an asynchronous write and call write_complete when it completes or fails 
	boost::asio::async_write(serialPort, 
		boost::asio::buffer(&writeMsgs.front(), 1), 
		boost::bind(&miniComClient::write_complete, 
		this, 
		boost::asio::placeholders::error));
}

void miniComClient::write_complete( const boost::system::error_code& error )
{
	// the asynchronous read operation has now completed or failed and returned an error 
	if (!error) 
	{ // write completed, so send next write data 
		writeMsgs.pop_front(); // remove the completed data 
		if (!writeMsgs.empty()) // if there is anthing left to be written 
			write_start(); // then start sending the next item in the buffer 
	} 
	else 
		do_close(error);
}

void miniComClient::do_close( const boost::system::error_code& error )
{
	// something has gone wrong, so close the socket & make this object inactive 
	if (error == boost::asio::error::operation_aborted) // if this call is the result of a timer cancel() 
		return; // ignore it because the connection cancelled the timer 
	if (error) ///@todo add Qt error handling
		cerr << "Error: " << error.message() << endl; // show the error message 
	else 
		cout << "Error: Connection did not succeed.\n"; 
	cout << "Press Enter to exit\n"; 

	serialPort.close(); 
}

void miniComClient::poll()
{
	ioService.poll();
}

miniComClient::~miniComClient()
{
	int nic = 100;
	nic++;
}
} //namespace vkbrd